#include "CppUTest/TestHarness.h"

extern "C"
{
#include "fwk/platform_queue.h"
#include "fwk/platform_errno.h"
#include "osal_time.h"
#include "hdf_log.h"
}

static struct PlatformQueue *g_queue;
static struct PlatformMsg g_msg1;
static struct PlatformMsg g_msg2;
static struct PlatformMsg *g_got1;
static struct PlatformMsg *g_got2;
static struct PlatformMsg *g_gotNull;
static bool g_msg1Handled;
static bool g_msg2Handled;

static struct PlatformQueue *g_workerQueue;


int32_t MsgHandleTest(struct PlatformQueue *queue, struct PlatformMsg *msg)
{
    HDF_LOGI("%s: queue name = %s, msg code:%d\n", __func__, queue->name, msg->code);
    if (msg->code == 0x1) {
       g_msg1Handled = true;
    } else if (msg->code == 0x2) {
       g_msg2Handled = true;
    }
    return HDF_SUCCESS;
}

TEST_GROUP(platform_queue_test)
{
    void setup()
    {
        g_msg1.code = 1;
        g_msg2.code = 2;
        g_got1 = g_got2 = g_gotNull = NULL;
        g_msg1Handled = g_msg2Handled = false;
        g_queue = PlatformQueueCreate(NULL, "test_queue", NULL);
        CHECK_FALSE(g_queue == NULL);
        g_workerQueue = PlatformQueueCreate(MsgHandleTest, "test_worker_queue", NULL);
        CHECK_FALSE(g_workerQueue == NULL);
        LONGS_EQUAL(HDF_SUCCESS, PlatformQueueStart(g_workerQueue));
    }

    void teardown()
    {
        PlatformQueueDestroy(g_queue);
        PlatformQueueDestroy(g_workerQueue);
    }
};

TEST(platform_queue_test, should_add_and_get_msg)
{
    int32_t ret;
    ret = PlatformQueueAddMsg(g_queue, &g_msg1);
    LONGS_EQUAL(ret, HDF_SUCCESS);
    ret = PlatformQueueGetMsg(g_queue, &g_got1, 0);
    LONGS_EQUAL(ret, HDF_SUCCESS);
    CHECK_TRUE(g_got1 == &g_msg1);
}

TEST(platform_queue_test, should_get_msg_by_order)
{
    PlatformQueueAddMsg(g_queue, &g_msg1);
    PlatformQueueAddMsg(g_queue, &g_msg2);
    PlatformQueueGetMsg(g_queue, &g_got1, 0);
    CHECK_TRUE(g_got1 == &g_msg1);
    PlatformQueueGetMsg(g_queue, &g_got2, 0);
    CHECK_TRUE(g_got2 == &g_msg2);
}

TEST(platform_queue_test, should_return_nodata_when_queue_emtpy)
{
    int32_t ret;
    ret = PlatformQueueGetMsg(g_queue, &g_gotNull, 0);
    LONGS_EQUAL(ret, HDF_PLT_ERR_NO_DATA);
    CHECK_TRUE(g_gotNull == NULL);
}

TEST(platform_queue_test, should_add_and_poll_msg)
{
    int32_t ret;
    ret = PlatformQueueAddMsg(g_queue, &g_msg1);
    LONGS_EQUAL(ret, HDF_SUCCESS);
    ret = PlatformQueueGetMsg(g_queue, &g_got1, HDF_WAIT_FOREVER);
    LONGS_EQUAL(ret, HDF_SUCCESS);
    CHECK_TRUE(g_got1 == &g_msg1);
}

TEST(platform_queue_test, should_poll_msg_by_order)
{
    int32_t ret;
    PlatformQueueAddMsg(g_queue, &g_msg1);
    PlatformQueueAddMsg(g_queue, &g_msg2);
    PlatformQueueGetMsg(g_queue, &g_got1, HDF_WAIT_FOREVER);
    CHECK_TRUE(g_got1 == &g_msg1);
    PlatformQueueGetMsg(g_queue, &g_got2, HDF_WAIT_FOREVER);
    CHECK_TRUE(g_got2 == &g_msg2);
    ret = PlatformQueueGetMsg(g_queue, &g_gotNull, 10);
    LONGS_EQUAL(ret, HDF_ERR_TIMEOUT);
    CHECK_TRUE(g_gotNull == NULL);
}

TEST(platform_queue_test, should_return_timeout_when_queue_keep_empty)
{
    int32_t ret;
    ret = PlatformQueueGetMsg(g_queue, &g_gotNull, 10);
    LONGS_EQUAL(ret, HDF_ERR_TIMEOUT);
    CHECK_TRUE(g_gotNull == NULL);
}

TEST(platform_queue_test, should_handle_msg_when_added)
{
    PlatformQueueAddMsg(g_workerQueue, &g_msg1);
    OsalMSleep(10);
    CHECK_TRUE(g_msg1Handled);
}

